package com.quan.commons.log.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.quan.commons.core.constant.CommonsConstant;
import com.quan.commons.core.properties.SystemValueProperties;
import com.quan.commons.core.utils.JwtUtils;
import com.quan.commons.core.utils.SpringContextHolder;
import com.quan.commons.log.annotation.LoginLog;
import com.quan.commons.log.event.SysLogEvent;
import com.quan.commons.log.utils.SysLogUtils;
import com.quan.system.entity.SysLog;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import static io.protostuff.MapSchema.MessageFactories.Map;


/**
 * 操作日志使用spring event异步入库
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect {

    @Around("@annotation(sysLog)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint point, com.quan.commons.log.annotation.SysLog sysLog) {
        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();

        Long startTime = System.currentTimeMillis();
        Object obj = point.proceed();
        Long endTime = System.currentTimeMillis();

        final SysLog systemLog = SysLogUtils.getSysLog();
        // 日志类型
        systemLog.setType(sysLog.type().getIndex());
        // 日志标题
        systemLog.setTitle(sysLog.value());
        // 执行时间
        systemLog.setTime(endTime - startTime);
        systemLog.setClassName(className);
        systemLog.setMethodName(methodName);

        // 发送异步日志事件
        SpringContextHolder.publishEvent(new SysLogEvent(systemLog));

        return obj;
    }

    /**
     * AOP切面记录用户登录
     * @param point
     * @param result
     */
    @AfterReturning(value="@annotation(com.quan.commons.log.annotation.LoginLog)", returning="result")
    @SneakyThrows
    public void afterReturning(JoinPoint point, Object result) {
        final SystemValueProperties properties = SpringContextHolder.getBean(SystemValueProperties.class);

        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        final LoginLog loginLog = method.getAnnotation(LoginLog.class);

        final String s = JSON.toJSONString(result);
        final JSONObject r = JSON.parseObject(s);

        final String token = r.get("token").toString();
        String userName = JwtUtils.getUserName(token, properties.getJwt().getSecret());

        final SysLog sysLog = SysLogUtils.getSysLogLogin();
        // 日志类型，登录，登出都统一使用登录
        sysLog.setType(CommonsConstant.LogTypeEnums.LOGIN.getIndex());
        // 日志标题
        sysLog.setTitle(loginLog.value());
        sysLog.setUsername(userName);

        // 发送异步日志事件
        SpringContextHolder.publishEvent(new SysLogEvent(sysLog));
    }

    @AfterThrowing(value="@annotation(com.quan.commons.log.annotation.SysLog)", throwing = "ex")
    public void doAfterThrowing(JoinPoint point, Exception ex) {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        String className = point.getTarget().getClass().getName();
        String methodName = methodSignature.getName();

        final com.quan.commons.log.annotation.SysLog sysLog = methodSignature.getMethod().getAnnotation(com.quan.commons.log.annotation.SysLog.class);

        final SysLog systemLog = SysLogUtils.getSysLog();
        // 日志类型
        systemLog.setType(3);
        // 日志标题
        systemLog.setTitle(sysLog.value());
        systemLog.setClassName(className);
        systemLog.setMethodName(methodName);
        // 异常信息
        systemLog.setException(ex.getMessage());

        // 发送异步日志事件
        SpringContextHolder.publishEvent(new SysLogEvent(systemLog));

    }

}
